package com.dynamic.mybatis.core.toolkit;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.dynamic.mybatis.core.metadata.MappedStatementMetaField;
import net.sf.cglib.beans.BeanMap;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author xs
 * @Date 2023/4/24 9:29
 */
public class TreeUtil {
    public static final String  childrenKey = "children";
    public static final String  idKey = "id";
    public static final String  parentIdKey = "parentId";
    public static final int  rootParentId = 0;

    /**
     * @Description: tree 转 list
     * @param tree 被转换对象
     * @param childKey 节点的子字段名
    　* @return 集合结构
    　*/
  public static <T> List<T> toArray(Object tree, String childKey) {
      if(tree == null){
          return Collections.EMPTY_LIST;
      }
      Collection<T> treeList = tree instanceof Collection ? (Collection) tree : Arrays.asList((T)tree) ;
      List<T> result = new ArrayList<>();
      for (T entity : treeList) {
          result.add(entity);
          Map beanMap = entity instanceof Map ? (Map) entity : BeanMap.create(entity);
          List<Object> children = (List<Object>) beanMap.get(childKey);
          if (children != null && children.size() > 0) {
              result.addAll(toArray(children,childKey));
          }
      }
      if (result.size() > 0) {
          for (int i = 0; i < result.size() ; i++) {
              Map beanMap = BeanUtils.copyGetMap(result.get(i));
              beanMap.put(childKey,null);
              result.set(i,BeanUtils.getBean(beanMap));
          }
      }
      return result;
    }

    public static <T> T setTree(T tree){
      return setTree(tree,rootParentId,parentIdKey,idKey,childrenKey);
    }

    /**
     * @Description: 给具有层级关系的树结构的id, parentId字段赋值
     * @param tree 被转换对象
     * @param rootParentId 根节点的父字段对应的值
     * @param parentIdKey 节点的父字段名
     * @param idKey 节点的唯一字段名
     * @param childKey 节点的子字段名
    　* @return 树形结构
    　*/
    public static <T> T setTree(T tree,int rootParentId,String parentIdKey,String idKey,String  childKey){
        return setTree(tree,rootParentId,new AtomicInteger(rootParentId),parentIdKey,idKey,childKey);
    }

    public static <T> T setTree(T tree, int rootParentId, AtomicInteger startId, String parentIdKey, String idKey, String  childKey){
        if(tree == null){ return tree;}
        Collection<Object> treeList = tree instanceof Collection ? (Collection) tree : Arrays.asList(tree);
        for(Object entity : treeList){
            Map beanMap = entity instanceof Map ? (Map) entity : BeanMap.create(entity);
            startId.set(startId.get()+1);
            beanMap.put(idKey,startId.get());
            beanMap.put(parentIdKey,rootParentId);
            setTree(beanMap.get(childKey),(int)beanMap.get(idKey),startId,parentIdKey,idKey,childKey);
        }
        return tree;
    }


    public static <T> List<T> toTree(Object array) {
      return  toTree(array,rootParentId,parentIdKey,idKey,childrenKey);
    }


        /**
        　* @Description: list 转 tree
        　* @param array 被转换对象
          * @param parentId 根节点的父字段对应的值
          * @param parentIdKey 节点的父字段名
          * @param idKey 节点的唯一字段名
          * @param childKey 节点的子字段名
        　* @return 树形结构
        　*/
    public static <T> List<T> toTree(Object array, Object parentId,String parentIdKey,String idKey,String  childKey) {
        Collection<T> treeList = array instanceof Collection ? (Collection) array : Arrays.asList((T)array) ;
        List<T> list = treeList.stream()
                // 过滤父节点
                .filter(parent ->  Objects.equals(BeanUtils.beanToMap(parent).get(parentIdKey),parentId))
                // 把父节点children递归赋值成为子节点
                .map(child -> {
                    Map childMap = BeanUtils.beanToMap(child);
                    childMap.put(childKey,toTree(treeList,childMap.get(idKey),parentIdKey,idKey,childKey));
                    return child;
                }).collect(Collectors.toList());
        return list;
    }

    public static void main(String[] args) {
        String idKey = "id";
        String parentKey = "parentId";
        String childKey = "children";

        List<Map<String,Object>> list = new ArrayList<>();
        Map<String,Object> map1 = new HashMap<>();
        map1.put("id",1);
        map1.put("parentId",0);
        map1.put("name","1");


        Map<String,Object> map2 = new HashMap<>();
        map2.put("id",2);
        map2.put("parentId",1);
        map2.put("name","2");

        Map<String,Object> map3 = new HashMap<>();
        map3.put("id",3);
        map3.put("parentId",2);
        map3.put("name","3");


        Map<String,Object> map4 = new HashMap<>();
        map4.put("id",4);
        map4.put("parentId",0);
        map4.put("name","4");

        list.add(map1);
        list.add(map2);
        list.add(map3);
        list.add(map4);


        List<Object> tree  = toTree(list,0,"parentId","id","children");

        List<MappedStatementMetaField> fieldTree =  JSON.parseArray(JSON.toJSONString(tree), MappedStatementMetaField.class);

        System.out.println("1 ====================================== ");
        setTree(fieldTree,-10,"parentId","id","children");
        System.out.println("  "+JSON.toJSONString(fieldTree, SerializerFeature.PrettyFormat));
        System.out.println("1 ====================================== ");


        System.out.println("  "+JSON.toJSONString(tree, SerializerFeature.PrettyFormat));

        List<Object> array  =   toArray(fieldTree,"children");


        System.out.println(JSON.toJSONString(array,SerializerFeature.PrettyFormat));

    }

}